package com.nexmo.hangman.service.utils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.nexmo.hangman.domain.Game;
import com.nexmo.hangman.domain.GameState;
import com.nexmo.hangman.domain.dto.GameStatusDto;
import com.nexmo.hangman.domain.dto.ManagementGameStatusDto;
import org.springframework.stereotype.Component;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
public class GameStatusDtoBuilder {

    public GameStatusDto buildFrom(Game game) {

        GameStatusDto gameStatusDto = new GameStatusDto();
        mapBasicInformation(gameStatusDto, game);
        return gameStatusDto;
    }

    private void mapBasicInformation(GameStatusDto gameStatusDto, Game game) {
        GameState gameState = game.getState();
        gameStatusDto.setGameId(game.getId());
        gameStatusDto.setLivesRemaining(gameState.getLivesRemaining());
        gameStatusDto.setHiddenWordLength(game.getWordToGuess().length());
        char[] charArray =  gameState.getIntroduced().toCharArray();
        Set<Character> notRepeatedSet = Sets.newHashSet();
        for(Character c : charArray) {
            notRepeatedSet.add(c);
        }
        Map<Character, List<Integer>> guessedMap = buildGuessedMap(game.getWordToGuess(),notRepeatedSet);
        gameStatusDto.setGuessed(guessedMap);
        gameStatusDto.setIntroduced(Lists.newArrayList(notRepeatedSet));
    }

    private Map<Character, List<Integer>> buildGuessedMap(String wordToGuess, Set<Character> introducedCharSet) {
        Map<Character, List<Integer>> guessedMap = Maps.newHashMap();
        for (Character c : introducedCharSet) {
            List guessedPositions = Utils.stringFindAll(wordToGuess, c);
            if(!guessedPositions.isEmpty()) {
                guessedMap.put(c,guessedPositions);
            }
        }
        return guessedMap;
    }

    public List<ManagementGameStatusDto> buildManagementEntityFrom(List<Game> games) {
        List<ManagementGameStatusDto> gameDtos = new LinkedList<ManagementGameStatusDto>();
        for (Game g : games) {
            ManagementGameStatusDto dto = new ManagementGameStatusDto();
            mapBasicInformation(dto, g);
            mapManagementInformation(dto, g);
            gameDtos.add(dto);
        }
        return gameDtos;
    }

    private void mapManagementInformation(ManagementGameStatusDto dto, Game game) {
        dto.setHiddenWord(game.getWordToGuess());
        dto.setUserName(game.getUser().getName());
    }
}
